/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"
#include "thttpd.h"
#include <sys/msg.h>
#include "shmem.h"
#define KB 1024
#define HTML_SIZE (64 * KB)

// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"
//登录函数
static int handle_login(int sock, const char *input) //input:值传递,将req_buf中的内容传递过来,input接收.(req_buf中存放post请求的数据)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username=");
    uname += strlen("username=");
    char *p = strstr(input, "password");
    *(p - 1) = '\0';
    printf("username = %s\n", uname);
    char *passwd = p + strlen("password=");
    printf("passwd = %s\n", passwd);

    
    if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0)//如果账号密码正确
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);//将uname重写进reply_buf
        strcat(reply_buf, "<script>window.location.href = '/1.html';</script>");//把回复内容拼接在reply_buf后（登陆成功把1.html传给浏览器）
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    else
    {
        printf("web login failed\n");
        //"用户名或密码错误"提示，chrome浏览器直接输送utf-8字符流乱码，没有找到太好解决方案，先过渡
        char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");//账号密码错误继续把登录文件传给浏览器
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    return 0;
}
//相加函数
static int handle_add(int sock, const char *input)
{
    int number1, number2;
    // input必须是"data1=1data2=6"类似的格式，注意前端过来的字符串会有双引号
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);
    char reply_buf[HTML_SIZE] = {0};
    printf("num = %d\n", number1 + number2);
    sprintf(reply_buf, "%d", number1 + number2);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);//处理完请求之后把结果发送回去
    return 0;
}
//消息队列
static int handle_ctrl(int sock, const char *input)//input:值传递,将req_buf中的内容传递过来,input接收.(req_buf中存放post请求的数据)
{
    // 创建消息队列     消息对列---请求正文
    	printf("open ctrl6666\n");
    key_t key = ftok("./main.c", 'a');
    int msgid = msgget(key,IPC_CREAT|IPC_EXCL|0666);
    if (msgid < 0)
    {
        if (errno == EEXIST)
        {
            msgid = msgget(key,0666);
        }
        else
        {
            perror("msgget err");
            return -1;
        }
    }
    //将数据信息加入到消息队列中
    msgsnd(msgid,input,64,0); //msgid:消息队列的id,input:指向消息的指针
    return 0;
}


static int handle_share(int sock, const char *input) 
{
   
    //共享内存
	printf("open share6666\n");
	key_t key = ftok("./main.c", 'a');
	if (key < 0)
	{
		perror("ftok err");
		return -1;
	}
	// printf("%#x\n", key);
	int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0666);
	if (shmid < 0)
	{
		if (errno == EEXIST)
		{
			// 打开共享内存  共享内存----响应正文
			shmid = shmget(key, 256, 0666);
		}
		else
		{
			perror("shmid create err");
			return -1;
		}
	}
	// 建立映射关系,p接收共享内存的值
	stat_t p = shmat(shmid, NULL, 0);
	if (p == (stat_t)-1)
	{
		perror("shmat err");
		return -1;
	}
	char buf[32]="";
	sprintf(buf,"%d,%d,%d,%d,%d,%d",p->registers,p->speedX,p->speedY,p->speedZ,p->coil,p->state);//从结构体中读出数据,按照相应格式存到buf里
   
    printf("buf:%s\n",buf);
    send(sock,buf,sizeof(buf),0);
     //struct shm_param para;
    // if(shm_init(&para,"shm",128)<0)
    // {
    //     printf("shm init err\n");
    //     return -1;
    // }
    // char *p=(char *)shm_getaddr(&para);
    // if(p==NULL)
    // {
    //     printf("shm get addr err\n");
    //     return-1;
    // }
    // strcpy(p,"666");
    // printf("%s\n",p);

    // shm_del(&para);
    // return 0;
}

/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
// 消息队列需要浏览器端传参,所以选用POST方式,下边这个函数就是POST处理逻辑的函数
int parse_and_process(int sock, const char *query_string, const char *input) // 根据不同请求,判断,处理数据,回复响应正文.
{
    // query_string不一定能用的到

    // 可以根据下边if的判断条件进行判断,对POST传过来的数据进行判断
    // 先处理登录操作
    // strstr(字符串1,字符串2,判断字符串2是否是字符串1的子串)
    if (strstr(input, "username=") && strstr(input, "password=")) //判断input里面是否包含username=(password=)
    {
        return handle_login(sock, input);
    }
    // 处理求和请求
    else if (strstr(input, "data1=") && strstr(input, "data2="))
    {
        return handle_add(sock, input);
    }
    else if (strstr(input, "colinum=") && strstr(input, "colistat="))
    {
        return handle_ctrl(sock, input);  
    }
    else if (strstr(input, "get"))
    {
//                     int num=666;

//  send(sock, num, sizeof(num), 0);
//  return num;
        return handle_share(sock,input);//当客户端发起post请求,且数据为get时,到这来调用这个函数
    }
    
    else // 剩下的都是json请求，这个和协议有关了
    {
        // 构建要回复的JSON数据
        const char *json_response = "{\"message\": \"Hello, client!\"}";

        // 发送HTTP响应给客户端
        send(sock, json_response, strlen(json_response), 0);
    }

    return 0;
}
